package xyz.icxl.android.architecture.data.net.okhttp.body

import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*
import xyz.icxl.android.architecture.data.net.okhttp.ProgressListener

/**
 * 文件描述：文件下载进度监听Body在Source.read()中监听下载进度
 *
 * 文件创建人：ChenXinLei
 *
 * 文件创建人联系方式：502616659(QQ)
 *
 * 创建时间：2020 年 08月 25 日
 *
 * 文件版本：v1.0
 *
 * 版本描述：创建文件
 *
 * 如何使用：
 * ```
OkHttpClient.Builder()
.addNetworkInterceptor {
val response = it.proceed(it.request())
val body = response.body() ?: return@addNetworkInterceptor response
val pBody = ProgressResponseBody(body) { progress ->
//利用progress值更新UI或处理其它业务逻辑
}
response.newBuilder()
.body(pBody)
.build()
}
 * ```
 */
class ProgressResponseForDownloadBody(
    private val responseBody: ResponseBody,
    private val progressListener: ProgressListener?
) : ResponseBody() {

    private val bufferedSource: BufferedSource by lazy {
        getWrappedSource(responseBody.source()).buffer()
    }

    override fun contentLength(): Long = responseBody.contentLength()

    override fun contentType(): MediaType? = responseBody.contentType()

    override fun source(): BufferedSource = bufferedSource

    private fun getWrappedSource(source: Source): Source = object : ForwardingSource(source) {
        private var bytesRead = 0L
        private val contentLength by lazy {
            contentLength() //避免重复调用
        }

        override fun read(sink: Buffer, byteCount: Long): Long {
            val bytes = super.read(sink, byteCount)
            if (bytes != -1L)
                bytesRead += bytes
            //进度监听回调
            val progress = bytesRead * 10000 / contentLength
            progressListener?.invoke(progress.toInt())
            return bytes
        }
    }
}

